Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


meshchatx/src/backend/database/__init__.py 666c90875aa810547703b5d00d304e8dd1917a4f (666c9087) Text, 11.76 KB

Tff7b72import T7ee787os
Tff7b72import T7ee787shutil
Tff7b72import T7ee787zipfile
Tff7b72from T7ee787datetime Tff7b72import Te6edf3UTCTb4b4b4, Te6edf3datetime

Tff7b72from T7ee787.T7ee787announces Tff7b72import Te6edf3AnnounceDAO
Tff7b72from T7ee787.T7ee787config Tff7b72import Te6edf3ConfigDAO
Tff7b72from T7ee787.T7ee787contacts Tff7b72import Te6edf3ContactsDAO
Tff7b72from T7ee787.T7ee787debug_logs Tff7b72import Te6edf3DebugLogsDAO
Tff7b72from T7ee787.T7ee787legacy_migrator Tff7b72import Te6edf3LegacyMigrator
Tff7b72from T7ee787.T7ee787map_drawings Tff7b72import Te6edf3MapDrawingsDAO
Tff7b72from T7ee787.T7ee787messages Tff7b72import Te6edf3MessageDAO
Tff7b72from T7ee787.T7ee787misc Tff7b72import Te6edf3MiscDAO
Tff7b72from T7ee787.T7ee787provider Tff7b72import Te6edf3DatabaseProvider
Tff7b72from T7ee787.T7ee787ringtones Tff7b72import Te6edf3RingtoneDAO
Tff7b72from T7ee787.T7ee787schema Tff7b72import Te6edf3DatabaseSchema
Tff7b72from T7ee787.T7ee787telemetry Tff7b72import Te6edf3TelemetryDAO
Tff7b72from T7ee787.T7ee787telephone Tff7b72import Te6edf3TelephoneDAO
Tff7b72from T7ee787.T7ee787voicemails Tff7b72import Te6edf3VoicemailDAO


Tff7b72class T56d364DatabaseTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3db_pathTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffprovider Tff7b72= Te6edf3DatabaseProviderTff7b72.Td2a8ffget_instanceTb4b4b4(Te6edf3db_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffschema Tff7b72= Te6edf3DatabaseSchemaTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffconfig Tff7b72= Te6edf3ConfigDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmessages Tff7b72= Te6edf3MessageDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffannounces Tff7b72= Te6edf3AnnounceDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmisc Tff7b72= Te6edf3MiscDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8fftelephone Tff7b72= Te6edf3TelephoneDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8fftelemetry Tff7b72= Te6edf3TelemetryDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffvoicemails Tff7b72= Te6edf3VoicemailDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffringtones Tff7b72= Te6edf3RingtoneDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffcontacts Tff7b72= Te6edf3ContactsDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmap_drawings Tff7b72= Te6edf3MapDrawingsDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdebug_logs Tff7b72= Te6edf3DebugLogsDAOTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4)

Tff7b72def Td2a8ffinitializeTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffschemaTff7b72.Td2a8ffinitializeTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffmigrate_from_legacyTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3reticulum_config_dirTb4b4b4, Te6edf3identity_hash_hexTb4b4b4)Tb4b4b4:
Te6edf3migrator Tff7b72= Te6edf3LegacyMigratorTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffproviderTb4b4b4,
Te6edf3reticulum_config_dirTb4b4b4,
Te6edf3identity_hash_hexTb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3migratorTff7b72.Td2a8ffshould_migrateTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3migratorTff7b72.Td2a8ffmigrateTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffexecute_sqlTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3queryTb4b4b4, Te6edf3paramsTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(Te6edf3queryTb4b4b4, Te6edf3paramsTb4b4b4)

Tff7b72def Td2a8ff_tune_sqlite_pragmasTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffexecute_sqlTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA wal_autocheckpoint=1000Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffexecute_sqlTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA temp_store=MEMORYTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffexecute_sqlTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA journal_mode=WALTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffSQLite pragma setup failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ff_get_pragma_valueTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pragmaTb4b4b4: Tffa657strTb4b4b4, Te6edf3defaultTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3cursor Tff7b72= Tff7b72selfTff7b72.Td2a8ffexecute_sqlTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffPRAGMA Tffd700{Te6edf3pragmaTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3row Tff7b72= Te6edf3cursorTff7b72.Td2a8fffetchoneTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3row Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3default
Tff7b72return Te6edf3rowTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Te6edf3default

Tff7b72def Td2a8ff_get_database_file_statsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72def Td2a8ffsize_forTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72return Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffgetsizeTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return T79c0ff0

Te6edf3db_path Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffdb_path
Te6edf3wal_path Tff7b72= Ta5d6fffTa5d6ff"Tffd700{Te6edf3db_pathTffd700}Ta5d6ff-walTa5d6ff"
Te6edf3shm_path Tff7b72= Ta5d6fffTa5d6ff"Tffd700{Te6edf3db_pathTffd700}Ta5d6ff-shmTa5d6ff"

Te6edf3main_bytes Tff7b72= Te6edf3size_forTb4b4b4(Te6edf3db_pathTb4b4b4)
Te6edf3wal_bytes Tff7b72= Te6edf3size_forTb4b4b4(Te6edf3wal_pathTb4b4b4)
Te6edf3shm_bytes Tff7b72= Te6edf3size_forTb4b4b4(Te6edf3shm_pathTb4b4b4)

Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffmain_bytesTa5d6ff"Tb4b4b4: Te6edf3main_bytesTb4b4b4,
Ta5d6ff"Ta5d6ffwal_bytesTa5d6ff"Tb4b4b4: Te6edf3wal_bytesTb4b4b4,
Ta5d6ff"Ta5d6ffshm_bytesTa5d6ff"Tb4b4b4: Te6edf3shm_bytesTb4b4b4,
Ta5d6ff"Ta5d6fftotal_bytesTa5d6ff"Tb4b4b4: Te6edf3main_bytes Tff7b72+ Te6edf3wal_bytes Tff7b72+ Te6edf3shm_bytesTb4b4b4,
Tb4b4b4}

Tff7b72def Td2a8ff_database_pathsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3db_path Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffdb_path
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffmainTa5d6ff"Tb4b4b4: Te6edf3db_pathTb4b4b4,
Ta5d6ff"Ta5d6ffwalTa5d6ff"Tb4b4b4: Ta5d6fffTa5d6ff"Tffd700{Te6edf3db_pathTffd700}Ta5d6ff-walTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffshmTa5d6ff"Tb4b4b4: Ta5d6fffTa5d6ff"Tffd700{Te6edf3db_pathTffd700}Ta5d6ff-shmTa5d6ff"Tb4b4b4,
Tb4b4b4}

Tff7b72def Td2a8ffget_database_health_snapshotTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3page_size Tff7b72= Tff7b72selfTff7b72.Td2a8ff_get_pragma_valueTb4b4b4(Ta5d6ff"Ta5d6ffpage_sizeTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4) Tff7b72or T79c0ff0
Te6edf3page_count Tff7b72= Tff7b72selfTff7b72.Td2a8ff_get_pragma_valueTb4b4b4(Ta5d6ff"Ta5d6ffpage_countTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4) Tff7b72or T79c0ff0
Te6edf3freelist_pages Tff7b72= Tff7b72selfTff7b72.Td2a8ff_get_pragma_valueTb4b4b4(Ta5d6ff"Ta5d6fffreelist_countTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4) Tff7b72or T79c0ff0
Te6edf3free_bytes Tff7b72= Tb4b4b4(
Te6edf3page_size Tff7b72* Te6edf3freelist_pages Tff7b72if Te6edf3page_size Tff7b72> T79c0ff0 Tff7b72and Te6edf3freelist_pages Tff7b72> T79c0ff0 Tff7b72else T79c0ff0
Tb4b4b4)

Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffquick_checkTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_get_pragma_valueTb4b4b4(Ta5d6ff"Ta5d6ffquick_checkTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffunknownTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffjournal_modeTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_get_pragma_valueTb4b4b4(Ta5d6ff"Ta5d6ffjournal_modeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffunknownTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffsynchronousTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_get_pragma_valueTb4b4b4(Ta5d6ff"Ta5d6ffsynchronousTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffwal_autocheckpointTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_get_pragma_valueTb4b4b4(Ta5d6ff"Ta5d6ffwal_autocheckpointTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffauto_vacuumTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_get_pragma_valueTb4b4b4(Ta5d6ff"Ta5d6ffauto_vacuumTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffpage_sizeTa5d6ff"Tb4b4b4: Te6edf3page_sizeTb4b4b4,
Ta5d6ff"Ta5d6ffpage_countTa5d6ff"Tb4b4b4: Te6edf3page_countTb4b4b4,
Ta5d6ff"Ta5d6fffreelist_pagesTa5d6ff"Tb4b4b4: Te6edf3freelist_pagesTb4b4b4,
Ta5d6ff"Ta5d6ffestimated_free_bytesTa5d6ff"Tb4b4b4: Te6edf3free_bytesTb4b4b4,
Ta5d6ff"Ta5d6fffilesTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_get_database_file_statsTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}

Tff7b72def Td2a8ff_checkpoint_walTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3modeTb4b4b4: Tffa657str Tff7b72= Ta5d6ff"Ta5d6ffTRUNCATETa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffexecute_sqlTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffPRAGMA wal_checkpoint(Tffd700{Te6edf3modeTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8fffetchallTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffrun_database_vacuumTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
T8b949e# Attempt to checkpoint WAL, ignore errors if busy
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_checkpoint_walTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffWarning: WAL checkpoint during vacuum failed (non-critical): Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffexecute_sqlTb4b4b4(Ta5d6ff"Ta5d6ffVACUUMTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_tune_sqlite_pragmasTb4b4b4(Tb4b4b4)

Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffhealthTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffget_database_health_snapshotTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
T8b949e# Wrap in a cleaner error message
Tff7b72raise Tf85149ExceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffDatabase vacuum failed: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffrun_database_recoveryTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3actions Tff7b72= Tb4b4b4[Tb4b4b4]

Te6edf3actionsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffstepTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffquick_check_beforeTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffresultTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_get_pragma_valueTb4b4b4(Ta5d6ff"Ta5d6ffquick_checkTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffunknownTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3actionsTff7b72.Td2a8ffappendTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffstepTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffwal_checkpointTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffresultTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_checkpoint_walTb4b4b4(Tb4b4b4)Tb4b4b4}Tb4b4b4)

Te6edf3integrity_rows Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffintegrity_checkTb4b4b4(Tb4b4b4)
Te6edf3integrity Tff7b72= Tb4b4b4[Te6edf3rowTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72for Te6edf3row Tff7b72in Te6edf3integrity_rowsTb4b4b4] Tff7b72if Te6edf3integrity_rows Tff7b72else Tb4b4b4[Tb4b4b4]
Te6edf3actionsTff7b72.Td2a8ffappendTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffstepTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffintegrity_checkTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffresultTa5d6ff"Tb4b4b4: Te6edf3integrityTb4b4b4}Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffvacuumTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_tune_sqlite_pragmasTb4b4b4(Tb4b4b4)

Te6edf3actionsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffstepTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffquick_check_afterTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffresultTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_get_pragma_valueTb4b4b4(Ta5d6ff"Ta5d6ffquick_checkTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffunknownTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffactionsTa5d6ff"Tb4b4b4: Te6edf3actionsTb4b4b4,
Ta5d6ff"Ta5d6ffhealthTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffget_database_health_snapshotTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}

Tff7b72def Td2a8ff_checkpoint_and_closeTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_checkpoint_walTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to checkpoint WAL: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to close database: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffcloseTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff"Ta5d6ffproviderTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffclose_allTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff"Ta5d6ffproviderTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffclose_allTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ff_backup_to_zipTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3backup_pathTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
Te6edf3paths Tff7b72= Tff7b72selfTff7b72.Td2a8ff_database_pathsTb4b4b4(Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3backup_pathTb4b4b4)Tb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
T8b949e# ensure WAL is checkpointed to get a consistent snapshot
Tff7b72selfTff7b72.Td2a8ff_checkpoint_walTb4b4b4(Tb4b4b4)

Te6edf3main_filename Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3pathsTb4b4b4[Ta5d6ff"Ta5d6ffmainTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72with Te6edf3zipfileTff7b72.Td2a8ffZipFileTb4b4b4(Te6edf3backup_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3compressionTff7b72=Te6edf3zipfileTff7b72.Td2a8ffZIP_DEFLATEDTb4b4b4) Tff7b72as Te6edf3zfTb4b4b4:
Te6edf3zfTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3pathsTb4b4b4[Ta5d6ff"Ta5d6ffmainTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3arcnameTff7b72=Te6edf3main_filenameTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3pathsTb4b4b4[Ta5d6ff"Ta5d6ffwalTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4:
Te6edf3zfTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3pathsTb4b4b4[Ta5d6ff"Ta5d6ffwalTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3arcnameTff7b72=Ta5d6fffTa5d6ff"Tffd700{Te6edf3main_filenameTffd700}Ta5d6ff-walTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3pathsTb4b4b4[Ta5d6ff"Ta5d6ffshmTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4:
Te6edf3zfTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3pathsTb4b4b4[Ta5d6ff"Ta5d6ffshmTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3arcnameTff7b72=Ta5d6fffTa5d6ff"Tffd700{Te6edf3main_filenameTffd700}Ta5d6ff-shmTa5d6ff"Tb4b4b4)

Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3backup_pathTb4b4b4,
Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4: Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffgetsizeTb4b4b4(Te6edf3backup_pathTb4b4b4)Tb4b4b4,
Tb4b4b4}

Tff7b72def Td2a8ffbackup_databaseTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3storage_pathTb4b4b4,
Te6edf3backup_pathTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3max_countTb4b4b4: Tffa657int Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4:
Te6edf3default_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_pathTb4b4b4, Ta5d6ff"Ta5d6ffdatabase-backupsTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3default_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3backup_path Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3timestamp Tff7b72= Te6edf3datetimeTff7b72.Td2a8ffnowTb4b4b4(Te6edf3UTCTb4b4b4)Tff7b72.Td2a8ffstrftimeTb4b4b4(Ta5d6ff"Ta5d6ff%Ta5d6ffYTa5d6ff%Ta5d6ffmTffd700%dTa5d6ff-Ta5d6ff%Ta5d6ffHTa5d6ff%Ta5d6ffMTa5d6ff%Ta5d6ffSTa5d6ff"Tb4b4b4)
Te6edf3backup_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3default_dirTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffbackup-Tffd700{Te6edf3timestampTffd700}Ta5d6ff.zipTa5d6ff"Tb4b4b4)

Te6edf3result Tff7b72= Tff7b72selfTff7b72.Td2a8ff_backup_to_zipTb4b4b4(Te6edf3backup_pathTb4b4b4)

T8b949e# Cleanup old backups if a limit is set
Tff7b72if Te6edf3max_count Tff7b72is Tff7b72not Tff7b72None Tff7b72and Te6edf3max_count Tff7b72> T79c0ff0Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3backups Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3file Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Te6edf3default_dirTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.zipTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3full_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3default_dirTb4b4b4, Te6edf3fileTb4b4b4)
Te6edf3stats Tff7b72= Te6edf3osTff7b72.Td2a8ffstatTb4b4b4(Te6edf3full_pathTb4b4b4)
Te6edf3backupsTff7b72.Td2a8ffappendTb4b4b4(Tb4b4b4(Te6edf3full_pathTb4b4b4, Te6edf3statsTff7b72.Td2a8ffst_mtimeTb4b4b4)Tb4b4b4)

Tff7b72if Tffa657lenTb4b4b4(Te6edf3backupsTb4b4b4) Tff7b72> Te6edf3max_countTb4b4b4:
T8b949e# Sort by modification time (oldest first)
Te6edf3backupsTff7b72.Td2a8ffsortTb4b4b4(Te6edf3keyTff7b72=Tff7b72lambda Te6edf3xTb4b4b4: Te6edf3xTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)
Te6edf3to_delete Tff7b72= Te6edf3backupsTb4b4b4[Tb4b4b4: Tffa657lenTb4b4b4(Te6edf3backupsTb4b4b4) Tff7b72- Te6edf3max_countTb4b4b4]
Tff7b72for Te6edf3pathTb4b4b4, Te6edf3_ Tff7b72in Te6edf3to_deleteTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to cleanup old backups: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72return Te6edf3result

Tff7b72def Td2a8ffcreate_snapshotTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3storage_pathTb4b4b4, Te6edf3nameTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
T8b949e"""Creates a named snapshot of the database."""
Te6edf3snapshot_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_pathTb4b4b4, Ta5d6ff"Ta5d6ffsnapshotsTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3snapshot_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
T8b949e# Ensure name is safe for filesystem
Te6edf3safe_name Tff7b72= Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(
Tb4b4b4[Te6edf3c Tff7b72for Te6edf3c Tff7b72in Te6edf3name Tff7b72if Te6edf3cTff7b72.Td2a8ffisalnumTb4b4b4(Tb4b4b4) Tff7b72or Te6edf3c Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff-Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff_Ta5d6ff"Tb4b4b4)Tb4b4b4]Tb4b4b4,
Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3safe_nameTb4b4b4:
Te6edf3safe_name Tff7b72= Ta5d6ff"Ta5d6ffunnamed_snapshotTa5d6ff"

Te6edf3snapshot_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3snapshot_dirTb4b4b4, Ta5d6fffTa5d6ff"Tffd700{Te6edf3safe_nameTffd700}Ta5d6ff.zipTa5d6ff"Tb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_backup_to_zipTb4b4b4(Te6edf3snapshot_pathTb4b4b4)

Tff7b72def Td2a8fflist_snapshotsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3storage_pathTb4b4b4)Tb4b4b4:
T8b949e"""Lists all available snapshots."""
Te6edf3snapshot_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_pathTb4b4b4, Ta5d6ff"Ta5d6ffsnapshotsTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3snapshot_dirTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[Tb4b4b4]

Te6edf3snapshots Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3file Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Te6edf3snapshot_dirTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.zipTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3full_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3snapshot_dirTb4b4b4, Te6edf3fileTb4b4b4)
Te6edf3stats Tff7b72= Te6edf3osTff7b72.Td2a8ffstatTb4b4b4(Te6edf3full_pathTb4b4b4)
Te6edf3snapshotsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3fileTb4b4b4[Tb4b4b4:Tff7b72-T79c0ff4Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3full_pathTb4b4b4,
Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4: Te6edf3statsTff7b72.Td2a8ffst_sizeTb4b4b4,
Ta5d6ff"Ta5d6ffcreated_atTa5d6ff"Tb4b4b4: Te6edf3datetimeTff7b72.Td2a8fffromtimestampTb4b4b4(
Te6edf3statsTff7b72.Td2a8ffst_mtimeTb4b4b4,
Te6edf3UTCTb4b4b4,
Tb4b4b4)Tff7b72.Td2a8ffisoformatTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72return Tffa657sortedTb4b4b4(Te6edf3snapshotsTb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3xTb4b4b4: Te6edf3xTb4b4b4[Ta5d6ff"Ta5d6ffcreated_atTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3reverseTff7b72=Tff7b72TrueTb4b4b4)

Tff7b72def Td2a8ffdelete_snapshot_or_backupTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3storage_pathTb4b4b4,
Te6edf3filenameTb4b4b4: Tffa657strTb4b4b4,
Te6edf3is_backupTb4b4b4: Tffa657bool Tff7b72= Tff7b72FalseTb4b4b4,
Tb4b4b4)Tb4b4b4:
T8b949e"""Deletes a database snapshot or auto-backup."""
Te6edf3base_dir Tff7b72= Ta5d6ff"Ta5d6ffdatabase-backupsTa5d6ff" Tff7b72if Te6edf3is_backup Tff7b72else Ta5d6ff"Ta5d6ffsnapshotsTa5d6ff"
Te6edf3file_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_pathTb4b4b4, Te6edf3base_dirTb4b4b4, Te6edf3filenameTb4b4b4)

T8b949e# Basic security check to ensure we stay within the intended directory
Te6edf3abs_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3file_pathTb4b4b4)
Te6edf3abs_base Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_pathTb4b4b4, Te6edf3base_dirTb4b4b4)Tb4b4b4)

Tff7b72if Tff7b72not Te6edf3abs_pathTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3abs_baseTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffInvalid pathTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)

Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3abs_pathTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3abs_pathTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffrestore_databaseTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3backup_pathTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3backup_pathTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffBackup not found at Tffd700{Te6edf3backup_pathTffd700}Ta5d6ff"
Tff7b72raise Tf85149FileNotFoundErrorTb4b4b4(Te6edf3msgTb4b4b4)

Te6edf3paths Tff7b72= Tff7b72selfTff7b72.Td2a8ff_database_pathsTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_checkpoint_and_closeTb4b4b4(Tb4b4b4)

T8b949e# clean existing files
Tff7b72for Te6edf3p Tff7b72in Te6edf3pathsTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3pTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3pTb4b4b4)

Tff7b72if Te6edf3zipfileTff7b72.Td2a8ffis_zipfileTb4b4b4(Te6edf3backup_pathTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3zipfileTff7b72.Td2a8ffZipFileTb4b4b4(Te6edf3backup_pathTb4b4b4, Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3zfTb4b4b4:
Te6edf3zfTff7b72.Td2a8ffextractallTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3pathsTb4b4b4[Ta5d6ff"Ta5d6ffmainTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffcopy2Tb4b4b4(Te6edf3backup_pathTb4b4b4, Te6edf3pathsTb4b4b4[Ta5d6ff"Ta5d6ffmainTa5d6ff"Tb4b4b4]Tb4b4b4)

T8b949e# reopen and retune
Tff7b72selfTff7b72.Td2a8ffinitializeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_tune_sqlite_pragmasTb4b4b4(Tb4b4b4)
Te6edf3integrity Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffintegrity_checkTb4b4b4(Tb4b4b4)

Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffrestored_fromTa5d6ff"Tb4b4b4: Te6edf3backup_pathTb4b4b4,
Ta5d6ff"Ta5d6ffintegrity_checkTa5d6ff"Tb4b4b4: Te6edf3integrityTb4b4b4,
Tb4b4b4}


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────